/*
 * Must include Big.js before this file
 */
window.CURRENCY_CONF = {
    prefixs: ['E', 'P', 'T', 'G', 'M', 'K', '1'],
    prefixs_zh_CN: ['亿', '万', '1'],
    prefixs_zh_TW: ['億', '萬', '1'],
    price_prefixs: ['B', 'M', 'K', '1'],
    price_prefixs_zh_CN: ['亿', '万', '1'],
    price_prefixs_zh_TW: ['億', '萬', '1'],
    scales: { 'E': 1e18, 'P': 1e15, 'T': 1e12, 'G': 1e9, 'M': 1e6, 'K': 1e3, '1': 1 },
    scales_zh_CN: { '亿': 1e8, '万': 1e4, '1': 1 },
    scales_zh_TW: { '億': 1e8, '萬': 1e4, '1': 1 },
    price_scales: { 'B': 1e9, 'M': 1e6, 'K': 1e3, '1': 1 },
    price_scales_zh_CN: { '亿': 1e8, '万': 1e4, '1': 1 },
    price_scales_zh_TW: { '億': 1e8, '萬': 1e4, '1': 1 },
    language: 'en_US',
    usd_cny: 6.3, // default
    globalUnit: localStorage.getItem('basicCurrency') || 'usd',
    block_coin_count: [
        { timstamp: 1231006505000, count: 50 },
        { timstamp: 1354116278000, count: 25 },
        { timstamp: 1468082773000, count: 12.5 },
        { timstamp: 1589225023000, count: 6.25 }
    ],
};
window.CURRENCY_FUNC = {
    /*
     * separate
     */
    separator: function(val) {
        if (typeof val === 'string') {
            // Keep effective number
            var numVal = Number(val);
            if (isNaN(numVal)) return 0;
            if (numVal > 1) {
                var arr = val.split('.');
                return arr[0].toLocaleString('en-US', { maximumFractionDigits: 10 }) + (arr[1] ? ('.' + arr[1]) : '');
            } else {
                return val;
            }
        } else {
            return val.toLocaleString('en-US', { maximumFractionDigits: 10 });
        }
    },
    /*
     * scale & separate
     */
    formatBigNum: function(value, digit, prefix) {
        var a = CURRENCY_FUNC.getScale(value, digit, prefix);
        return CURRENCY_FUNC.separator(a.result) + a.pre;
    },
    // 0 => 0.00
    formatBigNum_with_zero: function(value, digit, prefix) {
        if (value === 0) {
            return value.toFixed(digit);
        } else {
            var a = CURRENCY_FUNC.getScale(value, digit, prefix);
            return CURRENCY_FUNC.separator(a.result) + a.pre;
        }
    },
    // without toExponential
    formatBigNum_coin: function(value, digit, prefix) {
        var a = CURRENCY_FUNC.getScale(value, digit, prefix, false, true);
        return CURRENCY_FUNC.separator(a.result) + a.pre;
    },
    /*
     * exchange & separate
     * (unit of input value must be usd)
     */
    formatPrice: function(value, noExchange) {
        value = Number(value);
        var temp = CURRENCY_FUNC.exchange(value, noExchange);
        var digit = 2;
        if (Math.abs(temp) < 1) {
            digit = 4;
        }
        return CURRENCY_FUNC.separator(temp.toFixed(digit));
    },
    // formatPrice with specified digit
    formatPrice_digit: function(value, digit) {
        value = Number(value);
        if (digit === undefined) digit = 2;
        return CURRENCY_FUNC.separator(CURRENCY_FUNC.exchange(value).toFixed(digit));
    },
    // noExchange, digit = 2
    formatPrice_elec: function(value, noExchange) {
        value = Number(value);
        return CURRENCY_FUNC.separator(CURRENCY_FUNC.exchange(value, noExchange).toFixed(2));
    },
    formatPriceWithoutSeparator: function(value, noExchange) {
        value = Number(value);
        var temp = CURRENCY_FUNC.exchange(value, noExchange);
        var digit = 2;
        if (Math.abs(temp) < 1) {
            digit = 4;
        }
        return temp.toFixed(digit);
    },
    // for language of 'zh_CN/zh_TW': '亿'、'万'
    formatPrice_marketcap: function(value) {
        var scale = CURRENCY_CONF.language === 'zh_CN' ? (value > 1e5 ? '亿' : '万') : (CURRENCY_CONF.language === 'zh_TW' ? (value > 1e5 ? '億' : '萬') : null);
        var res = CURRENCY_FUNC.getScaleForPrice(CURRENCY_FUNC.exchange(value), false, scale);
        return CURRENCY_FUNC.separator(res.result) + res.pre;
    },
    // for language of 'zh_CN/zh_TW': '万'
    formatPrice_common: function(value, noExchange) {
        var scale = CURRENCY_CONF.language === 'zh_CN' ? '万' : (CURRENCY_CONF.language === 'zh_TW' ? '萬' : null);
        var res = CURRENCY_FUNC.getScaleForPrice(CURRENCY_FUNC.exchange(value), false, scale);
        return CURRENCY_FUNC.separator(res.result) + res.pre;
    },
    /*
     * scale
     * (prefix is always 'E|P|T|G|M|K')
     */
    formatHashrate: function(value, digit) {
        var a = CURRENCY_FUNC.getScale(value, digit || 2, null, 'usd');
        return a.result + a.pre;
    },
    remainRate: function(val) {
        if (!val.remain_minable || !val.total_supply) return 0;
        return Math.round(val.remain_minable / val.total_supply * 100);
    },
    // 2531004 → 253.1004万(zh_CN/zh_TW) | 2531.004k(en_US)
    getScale: function(value, digit, prefix, language, noExponential) {
        var temp = value;
        var result, pre;
        var language = language || CURRENCY_CONF.language;
        var prefixsConf = CURRENCY_CONF['prefixs_' + language] || CURRENCY_CONF['prefixs']
        var scalesConf = CURRENCY_CONF['scales_' + language] || CURRENCY_CONF['scales']
        if (digit === undefined) {
            digit = Math.abs(value) < 0.001 ? 4 : 2;
        }

        if (prefix) {
            result = CURRENCY_FUNC.getRound(value / (scalesConf[prefix] || 1), digit, noExponential);
            if (scalesConf[prefix] && result < 1 / Math.pow(10, digit)) {
                prefix = prefixsConf[prefixsConf.indexOf(prefix) + 1];
                if (prefix) {
                    result = CURRENCY_FUNC.getRound(value / scalesConf[prefix], digit, noExponential);
                }
            }
            pre = prefix;
        } else {
            for(var i = 0; i < prefixsConf.length; i++) {
                temp = value / scalesConf[prefixsConf[i]];
                if (temp < 10000) {
                    result = CURRENCY_FUNC.getRound(temp, digit, noExponential);
                    pre = prefixsConf[i];
                } else {
                    break;
                }
            }
        }
        if (!pre) {
            result = CURRENCY_FUNC.getRound(temp, digit, noExponential);
            pre = prefixsConf[i];
        }
        return { result: result, pre: pre === '1' ? '' : pre };
    },

    getScaleForPrice: function(value, digit, prefix, language) {
        var temp = value;
        var result, pre;
        var language = language || CURRENCY_CONF.language;
        var prefixsConf = CURRENCY_CONF['price_prefixs_' + language] || CURRENCY_CONF['price_prefixs']
        var scalesConf = CURRENCY_CONF['price_scales_' + language] || CURRENCY_CONF['price_scales']

        if (prefix) {
            var scaleVal = scalesConf[prefix] || 1;
            result = CURRENCY_FUNC.getRound(value / scaleVal, CURRENCY_FUNC.getDigitForPrice(value / scaleVal, digit));
            // for condition of too small number
            if (scalesConf[prefix] && result < 1 / Math.pow(10, digit)) {
                prefix = prefixsConf[prefixsConf.indexOf(prefix) + 1];
                if (prefix) {
                    result = CURRENCY_FUNC.getRound(value / scalesConf[prefix], CURRENCY_FUNC.getDigitForPrice(value / scalesConf[prefix], digit));
                }
            }
            pre = prefix;
        } else {
            for(var i = 0; i < prefixsConf.length; i++) {
                temp = value / scalesConf[prefixsConf[i]];
                if (temp < 10000) {
                    result = CURRENCY_FUNC.getRound(temp, CURRENCY_FUNC.getDigitForPrice(temp, digit));
                    pre = prefixsConf[i];
                } else {
                    break;
                }
            }
        }
        if (!pre) {
            result = CURRENCY_FUNC.getRound(temp, CURRENCY_FUNC.getDigitForPrice(temp, digit));
            pre = prefixsConf[i];
        }
        return { result: result, pre: pre === '1' ? '' : pre };
    },
    getDigitForPrice(value, digit) {
        return (!digit && digit !== 0) ? (Math.abs(value) < 1 ? 4 : 2) : digit;
    },

    // usd to other currency
    exchange: function(value, noExchange) {
        if (noExchange) return value;
        return CURRENCY_CONF.globalUnit === 'usd' ? value : value * CURRENCY_CONF['usd_' + CURRENCY_CONF.globalUnit];
    },

    // other currency to usd
    toUSD: function(value) {
        return CURRENCY_CONF.globalUnit === 'usd' ? value : value / CURRENCY_CONF['usd_' + CURRENCY_CONF.globalUnit];
    },

    getRound: function(value, digit, noExchange) {
        if (value === 0) return 0;
        return (Math.abs(value) < 0.001 && noExchange !== true) ? value.toExponential(digit) : value.toFixed(digit);
    },

    bindMoneyChange: function(container, changeBtn) {
        var $container = $(container || 'body');
        var $changeBtn = changeBtn ? $(changeBtn) : $container.find('.money-change');
        if (CURRENCY_CONF.globalUnit !==  'usd') $container.find('.money-name').html(CURRENCY_CONF.globalUnit.toUpperCase());

        $changeBtn.on('click', function() {
            var $name = $(this).find('.money-name');

            CURRENCY_CONF.globalUnit = $name.html() === 'USD' ? 'cny' : 'usd';
            $name.html(CURRENCY_CONF.globalUnit.toUpperCase());
            localStorage.setItem('basicCurrency', CURRENCY_CONF.globalUnit);

            CURRENCY_FUNC.updateMoney();
        });
    },
    updateMoney: function(container, defaultRule) {
        var $container = container ? container : $('body');
        var isUSD = CURRENCY_CONF.globalUnit === 'usd';
        $container.find('.money-symbol').each(function(idx, item) {
            item.innerHTML = isUSD ? '$' : '¥';
        });
        $container.find('.money-val').each(function(idx, item) {
            var $item = $(item);
            var rule = $item.data('rule') || defaultRule || 'formatBigNum';
            var data, val, noExchange, temp;
            data = $item.data('usd');
            if (!isUSD) {
                if (data) {
                    temp = $item.data('rmb');
                    if (!isNaN(temp)) {
                        noExchange = true;
                        data = temp;
                        $item.data('usd', data / CURRENCY_CONF['usd_' + CURRENCY_CONF.globalUnit]);
                    }
                }
            } else {
                if (data) {
                    $item.data('rmb', data * CURRENCY_CONF['usd_' + CURRENCY_CONF.globalUnit]);
                }
            }
            val = CURRENCY_FUNC[rule](data, noExchange);
            if (data) {
                if ($item.is('input')) {
                    $item.val(val);
                } else {
                    item.innerHTML = val;
                }
            }
        });
    },
    bindCalculate: function() {
        $('body').on('input', '.hash-val', function() {
            var $ipt = $(this);
            var $parent = $ipt.parents('.hash-val-container');
            var $profit = $parent.find('.profit-val');
            var $price = $parent.find('.price-val');
            var count = Number($ipt.val());
            if (isNaN(count)) return;
            $profit.each(function() {
                var $this = $(this);
                var profit = $this.data('profit');
                if (profit) {
                    var temp = count * profit;
                    $this.text(CURRENCY_FUNC.separator(CURRENCY_FUNC.getRound(temp, temp >= 1e6 ? 2 : (temp >= 100 ? 4 : 8), true)));
                }
            });
            $price.each(function() {
                var $this = $(this);
                var price = $this.data('usd-per');
                if (price) {
                    $this.data('usd', count * price);
                    $this.text(CURRENCY_FUNC.formatPrice(count * price));
                }
            });
        });
    },
    getRewardByTS: function(ts) {
        if (!ts) ts = moment().valueOf();
        var temp = CURRENCY_CONF.block_coin_count.reduce(function(pre, cur) {
            return ts >= cur.timstamp ? cur : pre;
        });
        return temp.count;
    },
    getRewardByHeight: function(height) {
        return Math.pow(2, -1 * Math.floor(height / 210000) + 1) * 25;
    },
    // estimated revenue per second per hash/s
    getSecondEstimatedRevenue: function(diff, ts, reward) {
        if (!reward) reward = CURRENCY_FUNC.getRewardByTS(ts);
        return Big(reward / Math.pow(2, 32) / diff);
    },
    getMinerEstimated: function (minerHashrate, diff, blockReward) {
        return Big(minerHashrate).div(diff).times(blockReward).times(86400).div(Math.pow(2, 32));
    },
    bindStickyHeader: function ($table, offsetTop) {
        var cutoffTop = $table.offset().top - (offsetTop || 128);
        var cutoffBottom = $table.offset().top + $table.innerHeight() - offsetTop;
        var $listArea = $('.list-area');
        var $listInner = $listArea.find('.list-container-inner');
        var $win = $(window);
        var lastTop = $win.scrollTop();
        $(window).on('scroll', function() {
            var winWidth = $win.width();
            var currentPosition = $win.scrollTop();
            var fixHeight = $table.find('.list-header').outerHeight() + $('.list-area-head').innerHeight() + ($('header.header-fix-top').innerHeight() || 0) + ($('.header-tips').innerHeight() || 0);
            // only large screen
            if (winWidth >= 768) {
                    if (currentPosition > cutoffTop && currentPosition < cutoffBottom) {
                        if (currentPosition >= lastTop || (currentPosition - $listInner.offset().top > fixHeight + 20 && currentPosition - $listInner.offset().top < $listArea.find('.list-container-left').height() - cutoffTop - 50)) {
                            if (!$listArea.hasClass('fixed-header')) {
                                $listArea.addClass('fixed-header');
                                if ($listArea.find('.list-container-inner .fix-padding').length === 0) {
                                    $listInner.prepend('<div class="fix-padding" style="height:' + fixHeight + 'px"></div>');
                                    if (currentPosition - $listInner.find('.list-container-left').offset().top < fixHeight + 20 && $listArea.data('scrollIntoView') !== false) {
                                        $listInner.get(0).scrollIntoView();
                                    }
                                }
                            }
                        } else {
                            if ($listArea.hasClass('fixed-header')) {
                                if ($listArea.find('.list-container-left').offset().top > currentPosition) {
                                    $listArea.find('.list-container-inner .fix-padding').remove();
                                    $listArea.removeClass('fixed-header');
                                }
                            }
                        }
                    } else {
                        $listArea.find('.list-container-inner .fix-padding').remove();
                        $listArea.removeClass('fixed-header');
                    }
            }
            CURRENCY_FUNC.updateListRightHeader();
            lastTop = currentPosition;
        });
    },
    updateListRightHeader: function() {
        var $listLeft = $('.list-container-left');
        var $listRight = $('.list-container-right');
        var $listRightHeader = $listRight.find('.list-header');
        if ($('.list-area').hasClass('fixed-header')) {
            $listRight.find('.list-header').css('width', $listRight.width() + 'px');
            $('.list-area-head-inner, .currency-select-container-web').css('width', $('.list-container-inner').width() + 'px');
        } else {
            $listRight.find('.list-header').css('width', $listRight.find('.list-body').width() + 'px');
        }
    },
    updateListHeaderStyle: function() {
        var $listLeft = $('.list-container-left');
        var $listRight = $('.list-container-right');

        CURRENCY_FUNC.updateListRightHeader();
        $listLeft.find('.list-header').css('width', $listLeft.width() + 'px');
        $listRight.find('.list-header .list-row').css('width', $listRight.find('.list-body').width() + 'px');
    },
    bindListRowHoverStyle: function() {
        $('.list-container').on('mouseenter', '.list-body .list-row', function(e) {
            var idx = $(this).parent().find('.list-row').index($(this));
            $('.list-container-left .list-body .list-row').eq(idx).addClass('active').siblings().removeClass('active');
            $('.list-container-right .list-body .list-row').eq(idx).addClass('active').siblings().removeClass('active');
        }).on('mouseleave', '.list-body .list-row', function() {
            var idx = $(this).parent().find('.list-row').index($(this));
            $('.list-container-left .list-body .list-row').eq(idx).removeClass('active');
            $('.list-container-right .list-body .list-row').eq(idx).removeClass('active');
        });
    }
};
